
#include "Win32.Drawing.Vectors.h"
#include "Win32.Number.h"

// -----------------------------------------------------------------------------

namespace Kif
{
namespace Win32
{
namespace Drawing
{

/// <summary>Allocate/Reallocate vectors</summary>
/// <param name="size">requested size</param>
/// <returns>true is returned if vector/s were allocated</returns>
bool Vectors::Alloc(long size)
{
   long sz = sizeof(double) * size;
   long iz = sizeof(int) * size;
   int *tc = (int*)Kif::Win32::Memory::alloc(iz);
   double *tx = (double*)Kif::Win32::Memory::alloc(sz);
   double *ty = (double*)Kif::Win32::Memory::alloc(sz);
   double *tz = (double*)Kif::Win32::Memory::alloc(sz);

   int c,t = (size < maxSize) ? size : maxSize;
   for (c=0; c < t; c++)
      tc[c] = command[c];

   if (x != NULL)
      CopyAxis(tx,size,x,maxSize);
   if (y != NULL)
      CopyAxis(ty,size,y,maxSize);
   if (z != NULL)
      CopyAxis(tz,size,z,maxSize);

   command = tc;
   x = tx;
   y = ty;
   z = tz;

   maxSize = size;

   return(true);
}  // allocate vectors

/// <summary>Given a line end-points add it to vectors</summary>
/// <param name="size">requested size</param>
/// <returns>true is returned if vector/s were allocated</returns>
long Vectors::Add(
   double x1, double y1, double z1, double x2, double y2, double z2)
{
   // if this are the first points enter just add those...
   if (Count == 0)
   {
      command[0] = CommandMove;
      x[0] = x1;
      y[0] = y1;
      z[0] = z1;

      command[1] = CommandDraw;
      x[1] = x2;
      y[1] = y2;
      z[1] = z2;
      Count += 2;
      return Count;
   }

   // see if we need to swap the previous two points...
   long i = Count - 2;
   double lx,ly,lz,w;

   lx = x[i];
   ly = y[i];
   lz = z[i];

   bool f1 = ComparePoints(x1,y1,z1,lx,ly,lz,Tolerance);
   bool f2 = ComparePoints(x2,y2,z2,lx,ly,lz,Tolerance);

   if (f1 || f2)
   {
      w = x[i]; x[i] = x[i+1]; x[i+1] = w;
      w = y[i]; y[i] = y[i+1]; y[i+1] = w;
      w = z[i]; z[i] = z[i+1]; z[i+1] = w;
   }

   // get last entered point

   i++;
   lx = x[i];
   ly = y[i];
   lz = z[i];

   bool f0 = ComparePoints(x1,y1,z1,x2,y2,z2,Tolerance);
   f1 = ComparePoints(x1,y1,z1,lx,ly,lz,Tolerance);
   f2 = ComparePoints(x2,y2,z2,lx,ly,lz,Tolerance);

   // all points are the same point, then the point is already in the set
   if (f0 && f1 && f2)
      return -1;

   if (f1)
   {
      if (f2)
         return -2;

      command[Count] = CommandDraw;
      x[Count] = x2;
      y[Count] = y2;
      z[Count] = z2;
      Count++;
   }
   else
   if (f2)
   {
      command[Count] = CommandDraw;
      x[Count] = x1;
      y[Count] = y1;
      z[Count] = z1;
      Count++;
   }
   else
   {
      command[Count] = CommandMove;
      x[Count] = x1;
      y[Count] = y1;
      z[Count] = z1;
      Count++;

      command[Count] = CommandDraw;
      x[Count] = x2;
      y[Count] = y2;
      z[Count] = z2;
      Count++;
   }

   return Count;
}  // end of Vectors

/// <summary>Given a line end-points add it to vectors</summary>
/// <param name="size">requested size</param>
/// <returns>true is returned if vector/s were allocated</returns>
long Vectors::Add(double x1, double y1, double z1)
{
   // if this are the first points enter just add those...
   if (Count == 0)
   {
      command[0] = CommandMove;
      x[0] = x1;
      y[0] = y1;
      z[0] = z1;
      Count++;
      return Count;
   }

   // get last entered point
   long i = Count - 1;
   double lx,ly,lz;

   lx = x[i];
   ly = y[i];
   lz = z[i];

   bool f1 = ComparePoints(x1,y1,z1,lx,ly,lz,Tolerance);

   // all points are the same point, then the point is already in the set
   if (f1)
      return -1;

   command[Count] = CommandDraw;
   x[Count] = x1;
   y[Count] = y1;
   z[Count] = z1;
   Count++;

   return Count;
}  // end of Vectors

// -----------------------------------------------------------------------------
// support to write vectort sets to disk

/// <summary>Open to write to a file</summary>
/// <param name="pFilePathName">file path name</param>
bool Vectors::FileOpen(TCHAR *pFilePathName)
{
   pOutputFile = new Kif::Win32::IO::TextFile();
   bool done = pOutputFile->OpenReadWrite(pFilePathName);
   if (!done)
   {
      delete pOutputFile;
      pOutputFile = NULL;
      return false;
   }

   Kif::Win32::String vecSet;
   vecSet.Copy(L"<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
   pOutputFile->WriteLine(&vecSet);

   vecSet.Copy(L"<");
   vecSet.Concat(Tags.VectorSets);
   vecSet.Concat(L" date=\"");
   vecSet.Concat(Kif::Win32::DateTime::GetYmdString());
   vecSet.Concat(L"\">");
   pOutputFile->WriteLine(&vecSet);

   return true;
}  // end of FileOpen

/// <summary>Store polygon set</summary>
/// <param name="pVectorSetName">Vector set name</param>
void Vectors::FileWrite(TCHAR *pVectorSetName)
{
   Kif::Win32::String c, n1, n2, n3;
   Kif::Win32::String vecSet;
   vecSet.Copy(L"   <");
   vecSet.Concat(Tags.VectorSet);
   vecSet.Concat(L" name=\"");
   vecSet.Concat(pVectorSetName);
   vecSet.Concat(L"\" count=\"");
   Kif::Win32::Number::ToString(n1,Count);
   vecSet.Concat(n1);
   vecSet.Concat(L"\">");
   pOutputFile->WriteLine(&vecSet);

   int i,precision=8;
   for (i=0; i < Count; i++)
   {
      Kif::Win32::Number::ToString(c,command[i]);
      Kif::Win32::Number::ToString(n1,x[i],precision);
      Kif::Win32::Number::ToString(n2,y[i],precision);
      Kif::Win32::Number::ToString(n3,z[i],precision);

      vecSet.Copy(L"      ");
      vecSet.Concat(c);
      vecSet.Concat(L" ");
      vecSet.Concat(n1);
      vecSet.Concat(L" ");
      vecSet.Concat(n2);
      vecSet.Concat(L" ");
      vecSet.Concat(n3);

      
      pOutputFile->WriteLine(&vecSet);
   }

   vecSet.Copy(L"   </");
   vecSet.Concat(Tags.VectorSet);
   vecSet.Concat(L">");
   pOutputFile->WriteLine(&vecSet);
}  // end of FileWrite

/// <summary>Close output file</summary>
void Vectors::FileClose()
{
   if (pOutputFile)
   {
      Kif::Win32::String vecSet;
      vecSet.Copy(L"</");
      vecSet.Concat(Tags.VectorSets);
      vecSet.Concat(L">");
      pOutputFile->WriteLine(&vecSet);

      pOutputFile->Close();
      delete pOutputFile;
      pOutputFile = NULL;
   }
}  // end of FileClose

}  // end of Kif.Drawing
}  // end of Kif.Win32
}  // end of Kif namespace

